/*
 * mirrorslist.cpp
 *
 *  Created on: Jan 4, 2009
 *      Author: HZ08494
 */

#include <wx/wx.h>
#include <wx/uri.h>
#include <wx/ffile.h>
#include <wx/arrimpl.cpp>
#include <wx/file.h>
#include <wx/stdpaths.h>

#include "mirrorslst.h"
#include "wininetstream.h"

WX_DEFINE_OBJARRAY(MirrorInfoArray);

MirrorsList::MirrorsList() {
}


bool MirrorsList::init() {
	_mirrorlst_path = wxString::Format(_T("%s%c%s"),
			wxStandardPaths::Get().GetUserDataDir().c_str(),
			wxFileName::GetPathSeparator(),
			_T("mirrors.lst")
		);
	
	wxFileName::Mkdir(wxStandardPaths::Get().GetUserDataDir(), 0777, wxPATH_MKDIR_FULL);
	
	return _reload_mirrors();
}

bool MirrorsList::reload_mirrors() {	
	// TODO: program will crash if can't internet connection is unavalible,
	// 		should I catch exceptions?
	// is a wx bug, I've reported it : #10337
	
	// open stream for fetch mirrors from internet
	
	WinINetInputStream mirror_stream(MIRRORS_LIST_URL);
	if ( !mirror_stream.IsOk() ) {
		wxMessageBox(wxString::Format(_("Can't download mirrors list from:%s, "
				"please check you have connected to the Internet, "
				"and try again later"), MIRRORS_LIST_URL));
		
		return false;
	}

	char buf[2048] = {0};
	wxFFile file(_mirrorlst_path, _T("w+") );
	
	if (file.Error()) {
		return false;
	}
	
	while ( !mirror_stream.Eof() ) { // save to file
		int len = mirror_stream.Read(buf,2048).LastRead();
		file.Write(buf, len);
	}
	
	file.Close();
	file.Detach();
	
	return _reload_mirrors();
}

bool MirrorsList::_reload_mirrors() {
	if ( !wxFile::Exists(_mirrorlst_path) ) {
		return false;
	}
	
	wxFFile file(_mirrorlst_path);
	
	if ( file.Error() ) {
		return false;
	}
	
	// init
	_continent_hash.clear();
	_country_hash.clear();
	_mirror_hash.clear();
	
	wxString name;
	wxString url;
	wxString continent;
	wxString country;
	
	char buf[2048] = {0};
	int i = 0;
	char c = '\0';
	
	
	// file->GetC();
	buf[0] = c;
	
	while (!file.Eof()) {
		int flag = 0;
		MirrorInfo mirrorinfo;
		
		// parse a line
		while (i<2048) {
			file.Read(&c,1);
			
			if (';'==c) {
				buf[i]= '\0';
				
				switch (flag) {
					case 0 :
						url = wxString::FromAscii(buf);
						break;
					case 1 :
						name = wxString::FromAscii(buf);
						break;
					case 2 :
						continent = wxString::FromAscii(buf);
						break;
					default :
						break; // will never reach here
				}

				flag++;
				i = 0;
				continue; // read next char
			} else if ( ('\n'==c || '\r'==c || file.Eof()) && strlen(buf)>0 ) { // line separator
				buf[i] = '\0';
				country = wxString::FromAscii(buf);
				i = 0;
				
				wxArrayString& temp = _continent_hash[continent];
				if (temp.Index(country)==wxNOT_FOUND) {
					temp.Add(country);
				}

				// get url scheme component
				// wxURI(url).GetScheme();
				name.Append(wxString::Format(_T(" (%s)"), 
						wxURI(url).GetScheme().c_str() ));
				
				_country_hash[country].Add(name);
				_mirror_hash[name] = url;
				_mirrors.Add(name);
				
				buf[0] = '\0';
				break; // parse next line
			} else if (file.Eof()) {
				break; // end of parse
			} else {
				buf[i] = c;
				i++;
			}
		} // end parse line
	}
	
	ArrayStringHash::iterator it;
    for( it=_continent_hash.begin(); it!=_continent_hash.end(); ++it ) {
    	it->second.Sort();
    }
    
    for( it=_country_hash.begin(); it!=_country_hash.end(); ++it ) {
    	it->second.Sort();
    }
	
	return true;
}

MirrorsList::~MirrorsList() {
	// TODO Auto-generated destructor stub
}

MirrorsList MirrorsList::self;
